package saxion.speelveld.spaceengineer.database;

import java.util.ArrayList;

import saxion.speelveld.spaceengineer.model.Building;
import saxion.speelveld.spaceengineer.model.BuildingTile;
import saxion.speelveld.spaceengineer.model.InfrastructureTile;
import saxion.speelveld.spaceengineer.model.ObstacleTile;
import saxion.speelveld.spaceengineer.model.ResourceTile;
import saxion.speelveld.spaceengineer.model.ResourceType;
import saxion.speelveld.spaceengineer.model.Tile;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class TileDAO
{
	private SQLiteDatabase database;

	private TileDB dbHelper;

	private BuildingDAO buildingDatasource;

	private BuildingTypeDAO buildingTypeDatasource;

	public TileDAO(Context context)
	{
		dbHelper = new TileDB(context);
		buildingDatasource = new BuildingDAO(context);
		buildingTypeDatasource = new BuildingTypeDAO(context);
	}

	/**
	 * Open the database connection.
	 * 
	 * @throws SQLException
	 */
	public void open() throws SQLException
	{
		database = dbHelper.getWritableDatabase();
	}

	/**
	 * Close the database connection.
	 */
	public void close()
	{
		dbHelper.close();
	}

	/**
	 * returns the saved tiles from the database that correspond with the gameId.
	 * 
	 * @param gameId
	 * @param buildingList
	 * @return Array of tiles (rows x columns)
	 */
	public Tile[][] GetTileArrayForGame(int gameId, ArrayList<Building> buildingList)
	{
		Tile[][] tileArray = new Tile[100][100];

		Cursor cursor = database.rawQuery("SELECT * FROM " + TileDB.TABLE_NAME + " WHERE " + TileDB.COLUMN_GAMEID
			+ " = " + gameId, null);

		boolean isResource = false;
		boolean isObstacle = false;
		boolean isBuilding = false;
		boolean isInfrastructure = false;

		cursor.moveToFirst();
		while (cursor.isAfterLast() == false)
		{
			isResource = false;
			isObstacle = false;
			isBuilding = false;
			isInfrastructure = false;

			int backgroundID = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_TILEBACKGROUNDID));
			int tilePositionX = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_TILEROW));
			int tilePositionY = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_TILECOL));

			if (cursor.isNull(cursor.getColumnIndex(TileDB.COLUMN_RESOURCEORDINAL)) == false)
			{
				isResource = true;
			}
			else if (cursor.isNull(cursor.getColumnIndex(TileDB.COLUMN_OBSTACLEID)) == false)
			{
				isObstacle = true;
			}
			else if (cursor.isNull(cursor.getColumnIndex(TileDB.COLUMN_BUILDINGID)) == false)
			{
				isBuilding = true;
			}
			else if (cursor.isNull(cursor.getColumnIndex(TileDB.COLUMN_INFRASTRUCTURECONNECTION)) == false)
			{
				isInfrastructure = true;
			}

			int tileResourceOrdinal = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_RESOURCEORDINAL));
			int tileObstacleId = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_OBSTACLEID));
			int tileBuildingId = cursor.getInt(cursor.getColumnIndex(TileDB.COLUMN_BUILDINGID));
			String tileInfraConnection = cursor
				.getString(cursor.getColumnIndex(TileDB.COLUMN_INFRASTRUCTURECONNECTION));

			Tile tile = null;

			if (isResource == true)
			{
				tile = new ResourceTile(backgroundID, ResourceType.values()[tileResourceOrdinal]);
			}
			else if (isObstacle == true)
			{
				// Log.i("getTileArrayForGame", "obstalcePicId: " + tileObstacleId);
				tile = new ObstacleTile(backgroundID, tileObstacleId);
			}
			else if (isBuilding == true)
			{
				buildingDatasource.open();
				Log.w("GetTileArrayForGame", "trying this with: " + tileBuildingId);
				Building retBuilding = buildingDatasource.getBuilding(tileBuildingId, buildingList);
				if (retBuilding != null)
				{
					int partX = tilePositionX - retBuilding.getBuildingPointInFieldX();
					int partY = tilePositionY - retBuilding.getBuildingPointInFieldY();
					tile = new BuildingTile(backgroundID, retBuilding, partX, partY);
				}

				buildingDatasource.close();
			}
			else if (isInfrastructure == true)
			{
				tile = new InfrastructureTile(backgroundID);
				((InfrastructureTile) tile).setConnectionVarsFromString(tileInfraConnection);
			}

			if (tile == null)
			{
				tile = new Tile(backgroundID);
			}
			tile.setDirty(false);
			tileArray[tilePositionX][tilePositionY] = tile;
			cursor.moveToNext();
		}
		cursor.close();
		return tileArray;
	}

	/***
	 * 
	 * @param gameId
	 * @param tile
	 * @param xRow
	 * @param yCol
	 */
	public void PutTile(int gameId, Tile tile, int xRow, int yCol, boolean tileAlreadyExists)
	{

		ContentValues values = new ContentValues();
		values.put(TileDB.COLUMN_TILEROW, xRow);
		values.put(TileDB.COLUMN_TILECOL, yCol);
		values.put(TileDB.COLUMN_GAMEID, gameId);
		values.put(TileDB.COLUMN_TILEBACKGROUNDID, tile.getBackgroundID());

		if (tile instanceof BuildingTile)
		{
			// Log.i("putTile", "tile " + xRow + "/" + yCol + ": is a BuildingTile");

			try
			{
				buildingTypeDatasource.open();
				// String buildingName = ((BuildingTile) tile).getBuilding().getBuildingName();

				// values.put(TileDB.COLUMN_BUILDINGID, buildingTypeDatasource.GetTypeIdByName(buildingName));
				values.putNull(TileDB.COLUMN_RESOURCEORDINAL);
				values.putNull(TileDB.COLUMN_OBSTACLEID);
				values.put(TileDB.COLUMN_BUILDINGID, ((BuildingTile) tile).getBuilding().getBuildingId());
			}
			finally
			{
				buildingTypeDatasource.close();
			}
		}
		else if (tile instanceof ResourceTile)
		{
			values.put(TileDB.COLUMN_RESOURCEORDINAL, ((ResourceTile) tile).getResourceType().ordinal());
		}
		else if (tile instanceof ObstacleTile)
		{

			values.put(TileDB.COLUMN_OBSTACLEID, ((ObstacleTile) tile).getObstaclePicID());
			// Log.i("putTile",
			// "tile " + xRow + "/" + yCol + ": is a ObstacleTile - " + values.getAsInteger(TileDB.COLUMN_OBSTACLEID));
		}
		else if (tile instanceof InfrastructureTile)
		{
			// Log.i("putTile", "tile " + xRow + "/" + yCol + ": is a InfrastructureTile");
			String connection = getInfraConnectionAsString((InfrastructureTile) tile);
			Log.i("PutTile.settingInfraStructureConnection", connection);
			values.put(TileDB.COLUMN_INFRASTRUCTURECONNECTION, connection);

		}

		if (tileAlreadyExists == false)
		{
			// insert
			database.insert(TileDB.TABLE_NAME, null, values);
		}
		else
		{
			// update
			int updateCount = database.update(TileDB.TABLE_NAME, values, TileDB.COLUMN_GAMEID + "=? AND "
				+ TileDB.COLUMN_TILEROW
				+ "=? AND " + TileDB.COLUMN_TILECOL + "=?",
				new String[] { Integer.toString(gameId), Integer.toString(xRow), Integer.toString(yCol) });
			// Log.e("PutTile.Updating", updateCount + "");
		}
	}

	private String getInfraConnectionAsString(InfrastructureTile infra)
	{
		String retString = "";
		int isConnected = infra.isConnectedLeft() ? 1 : 0;
		retString = retString + isConnected;
		isConnected = infra.isConnectedTop() ? 1 : 0;
		retString = retString + isConnected;
		isConnected = infra.isConnectedRight() ? 1 : 0;
		retString = retString + isConnected;
		isConnected = infra.isConnectedBottom() ? 1 : 0;
		retString = retString + isConnected;

		return retString;
	}

	public void beginTransactionMode()
	{
		database.beginTransaction();
	}

	public void setTransactionModeSuccesfull()
	{
		database.setTransactionSuccessful();
	}

	public void endTransactionMode()
	{
		database.endTransaction();
	}
}
